<?php

namespace common\service;

use common\model\MemberModel;
use common\model\SaasProjectModel;
use support\ErrorCode;
use support\SingletonTrait;
use think\Exception;
use Throwable;

class MemberService
{
    use SingletonTrait;

    /**
     * 导入计划
     * @param $dataList
     * @param $tenantId
     * @return mixed
     * @throws Exception
     * @throws Throwable
     */
    public function import($dataList, $tenantId)
    {
        $projectList = model(SaasProjectModel::class)->where(['tenant_id' => $tenantId])->select();
        $projectList = array_column($projectList, null, 'name');

        $showStepCategoryList = teamones_request('teamones-saas', 'project/get_show_step_category_group', []);
        $showStepCategoryMap = array_column($showStepCategoryList['data'], null, 'name');

        $memberCommonService = CommonService::instance('member');
        $filter = [];
        $this->validateAndFormatData($dataList, $projectList, $showStepCategoryMap, $filter);
        $oldMemberList = $this->getOldData($filter);
        $oldMemberList = array_column($oldMemberList, null, 'unique_key');

        // 组装更新和插入数据
        $insertList = [];
        $updateList = [];
        $insertMap = [];
        $insertLen = 0;
        $updateMap = [];
        $updateLen = 0;

        unset($data);
        foreach ($dataList as $data) {
            if ($data['flag'] === false) {
                continue;
            }
            $data['step_category_ids'] = json_encode($data['step_category_ids']);
            $oldMember = $oldMemberList[$data['unique_key']] ?? null;
            if (empty($oldMember)) {
                // 新增
                // 后来的覆盖前面的
                $dealData = $memberCommonService->dealCreateCustomField($data, 'member');
                ksort($dealData);
                $dealData['created'] = time();
                $dealData['created_by'] = fill_created_by();
                $dealData['tenant_id'] = auto_fill_tenant_id();
                if (!isset($insertMap[$data['unique_key']])) {
                    $insertList[] = $dealData;
                    $insertMap[$data['unique_key']] = $insertLen;
                    $insertLen += 1;
                } else {
                    $insertList[$insertMap[$data['unique_key']]] = $dealData;
                }
            } else {
                // 更新
                $updateItem = [];
                // 对比出需要更新的字段
                foreach ($data as $k => $v) {
                    if (!isset($oldMember[$k])) {
                        continue;
                    }
                    if ($oldMember[$k] == $v) {
                        continue;
                    }
                    $updateItem[$k] = $v;

                }
                if (!empty($updateItem)) {
                    $updateItem['id'] = $oldMember['id'];
                    $updateItem['updated'] = time();
                    $updateItem['updated_by'] = fill_created_by();
                    if (!isset($updateMap[$data['unique_key']])) {
                        $updateList[] = $updateItem;
                        $updateMap[$data['unique_key']] = $updateLen;
                        $updateLen += 1;
                    } else {
                        $updateList[$updateMap[$data['unique_key']]] = $updateItem;
                    }
                }
            }
        }

        if (empty($insertList) && empty($updateList)) {
            return $dataList;
        }

        // 批量事务操作
        model(MemberModel::class)->startTrans();

        try {
            if (!empty($insertList)) {
                model(MemberModel::class)->addAll($insertList);
            }
            if (!empty($updateList)) {
                foreach ($updateList as $updateItem) {
                    model(MemberModel::class)->save($updateItem);
                }
            }
            model(MemberModel::class)->commit();
        } catch (Throwable $e) {
            model(MemberModel::class)->rollback();
            throw $e;
        }

        return $dataList;
    }

    /**
     * 验证并格式化数据
     * @param $dataList
     * @param array $projectList
     * @param array $showStepCategoryMap
     * @param $filter
     * @return void
     */
    private function validateAndFormatData(&$dataList, array $projectList, array $showStepCategoryMap, &$filter)
    {
        $phoneList = [];
        foreach ($dataList as &$data) {
            $data['flag'] = false;
            $data['month_time'] = strtotime($data['month_date']);
            $phoneList[$data['phone']] = $data['phone'];
            if ($data['month_time'] === false) {
                $data['err_msg'] = '月份时间有误';
                $data['err_code'] = ErrorCode::MONTH_DATE_INVALID;
                continue;
            }
            if (!isset($projectList[$data['project_name']])) {
                $data['err_msg'] = '项目找不到';
                $data['err_code'] = ErrorCode::PROJECT_NOT_FOUND;
                continue;
            }
            $data['project_id'] = $projectList[$data['project_name']]['id'];
            if (!isset($showStepCategoryMap[$data['step_category_name']])) {
                $data['err_msg'] = '环节找不到';
                $data['err_code'] = ErrorCode::SHOW_STEP_CATEGORY_NOT_FOUND;
                continue;
            }
            $data['step_category_ids'] = $showStepCategoryMap[$data['step_category_name']]['children_ids'];

            $data['flag'] = true;
        }
        $userList = [];
        if (!empty($phoneList)) {
            $userList = teamones_request('teamones-im', 'user/select', [
                'param' => [
                    'filter' => [
                        'phone' => [
                            '-in', implode(',', $phoneList),
                        ],
                    ],
                ],
            ],
            );
            $userList = array_column($userList['data']['rows'], null, 'phone');
        }

        foreach ($dataList as &$data) {
            if (!$data['flag']) {
                continue;
            }
            if (!isset($userList[$data['phone']])) {
                $data['flag'] = false;
                $data['err_msg'] = '用户找不到';
                $data['err_code'] = ErrorCode::USER_NOT_FOUND;
                continue;
            }
            $data['user_id'] = $userList[$data['phone']]['id'];
            $data['flag'] = true;

            $filter[] = [
                'user_id' => $data['user_id'],
                'month_time' => $data['month_time'],
            ];
            $data['unique_key'] = sprintf("%d#%d", $data['user_id'], $data['month_time']);
        }
    }

    /**
     * 计划列表
     * @param $filter
     * @param array $page
     * @return array
     * @throws Exception
     */
    function list($filter, array $page) {
        $res = [
            'total' => model(MemberModel::class)->where($filter)->count(),
            'rows' => model(MemberModel::class)->where($filter)->page(...$page)->select(),
        ];

        if (empty($res['rows'])) {
            return $res;
        }
        $projectIdList = [];
        $userIdList = [];
        foreach ($res['rows'] as $row) {
            $projectIdList[$row['project_id']] = $row['project_id'];
            $userIdList[$row['user_id']] = $row['user_id'];
        }
        $projectList = model(SaasProjectModel::class)->where(['id' => ['IN', implode(',', $projectIdList)]])->field('id,name')->select();
        $projectList = array_column($projectList, null, 'id');
        $userList = teamones_request('teamones-im', 'user/select', ['param' => ['filter' => [
            'id' => [
                '-in', implode(',', $userIdList),
            ],
        ]]]);
        $userList = array_column($userList['data']['rows'], null, 'id');
        foreach ($res['rows'] as &$row) {
            CommonService::instance('member')->getFormatAttrData($row);
            $row['project'] = $projectList[$row['project_id']] ?? null;
            $row['user'] = $userList[$row['user_id']] ?? null;
        }
        return $res;
    }

    /**
     * 查询历史数据
     * @param array $filter
     * @return array|false|mixed|string
     */
    private function getOldData(array $filter)
    {
        if (empty($filter)) {
            return [];
        }
        if (count($filter) > 1) {
            $filter['_logic'] = 'OR';
            $filter = [$filter];
        } else {
            $filter = $filter[0];
        }
        // 查询历史成员信息
        return model(MemberModel::class)
            ->where($filter)
            ->field("id,project_id,step_category_ids,step_category_name,grade,concat(user_id,'#',month_time) unique_key")
            ->select();
    }
}
